﻿using Eve;
using Invest.Data;
using MongoDB.Driver;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    static class testeve
    {
        static NLog.ILogger _logger = NLog.LogManager.GetCurrentClassLogger();

        public static async Task TestAsync()
        {
            // 初始化
            var client = new EveClient
            {
                BaseAddress = new Uri("http://127.0.0.1/vst/"),
                //Authenticator = new BasicAuthenticator("user", "pw")
            };

            // 为随后的请求设置目标资源
            client.ResourceName = "supplyitem";

            var items = await client.GetAsync<supplyitem>();
            if (client.HttpResponse.StatusCode != HttpStatusCode.OK)
                return;

            _logger.Info("获取到{0}个数据", items.Count);

            foreach (var item in items)
            {
                _logger.Info("{0} {1} {2}", item.name, item.time, item.tag);
            }
        }

        public static async Task Test2Async()
        {
            // 初始化
            var client = new EveClient
            {
                BaseAddress = new Uri("http://127.0.0.1/vst/"),
                //Authenticator = new BasicAuthenticator("user", "pw")
            };

            // 为随后的请求设置目标资源
            client.ResourceName = "supplyitem";

            // Returns a List<T> which only includes changed items since a DateTime.
            var ifModifiedSince = DateTime.Now.AddDays(-1);
            var items = await client.GetAsync<supplyitem>(ifModifiedSince);
            if (client.HttpResponse.StatusCode != HttpStatusCode.OK)
                return;

            _logger.Info("获取到{0}个数据", items.Count);

            foreach (var item in items)
            {
                _logger.Info("{0} {1} {2}", item.name, item.time, item.tag);
            }
        }

        public static async Task Test3Async()
        {
            // 初始化
            var client = new EveClient
            {
                BaseAddress = new Uri("http://127.0.0.1/vst/"),
                //Authenticator = new BasicAuthenticator("user", "pw")
            };

            // 为随后的请求设置目标资源
            client.ResourceName = "supplyitem";

            var items = await client.GetAsync<supplyitem>();
            if (client.HttpResponse.StatusCode != HttpStatusCode.OK)
                return;

            var item = items[0];

            // Update an existing object silently performing a If-None-Match request based
            // on object ETag.  See http://python-eve.org/features#conditional-requests
            item = await client.GetAsync<supplyitem>(item);

            // StatusCode is 'NotModified' since ETag matches the one on the server (no
            // download was performed). Would be OK if a download happened. Object did not
            // change.
            if (client.HttpResponse.StatusCode != HttpStatusCode.NotModified)
                return;

            _logger.Info("OK");
        }

        public static async Task Test4Async()
        {
            // 初始化
            var client = new EveClient
            {
                BaseAddress = new Uri("http://127.0.0.1/vst/"),
                //Authenticator = new BasicAuthenticator("user", "pw")
            };

            // 为随后的请求设置目标资源
            client.ResourceName = "supplyitem";

            // Raw, conditional GET request
            var companyId = "9be565c1-6245-3443-a6ea-3e5076fee8d5";
            var eTag = "ca27f7ffddb71002323d5ce85de416724e2fe4c9";

            var item = await client.GetAsync<supplyitem>("supplyitem", companyId, eTag);

            // HttpStatusCode is still 'NotModified'.
            if (client.HttpResponse.StatusCode != HttpStatusCode.NotModified)
                return;

            _logger.Info("{0} {1} {2}", item.name, item.time, item.tag);
        }

        public static async Task Test5Async()
        {
            // 初始化
            var client = new EveClient
            {
                BaseAddress = new Uri("http://127.0.0.1/vst/"),
                //Authenticator = new BasicAuthenticator("user", "pw")
            };

            // 为随后的请求设置目标资源
            client.ResourceName = "supplyitem";

            // POST/Create Requests

            var item = await client.PostAsync<supplyitem>(new supplyitem { name = "MyCompany" });

            // HttpStatusCode is 'Created'.
            if (HttpStatusCode.Created != client.HttpResponse.StatusCode)
                return;

            _logger.Info("", item.name);
            //Assert.IsInstanceOf<DateTime>(company.Updated);
            //Assert.IsNotNullOrEmpty(company.UniqueId);
            //Assert.IsNotNullOrEmpty(company.ETag);
        }

        public static async Task Test6Async()
        {
            // 初始化
            var client = new EveClient
            {
                BaseAddress = new Uri("http://127.0.0.1/vst/"),
                //Authenticator = new BasicAuthenticator("user", "pw")
            };

            // 为随后的请求设置目标资源
            client.ResourceName = "supplyitem";

            // PUT/Replace Requests

            var item = await client.PostAsync<supplyitem>(new supplyitem { name = "MyCompany" });
            item.name = "YourCompany";

            // PUT requests will silently perform a If-Match request so server copy will only be
            // updated if server and document ETag match.
            // See http://python-eve.org/features#data-integrity-and-concurrency-control
            var result = await client.PutAsync<supplyitem>(item);

            if (HttpStatusCode.OK != client.HttpResponse.StatusCode)
                return;

            //Assert.AreEqual(result.Name, item.Name);

            //// UniqueId and Created did not change.
            //Assert.AreEqual(result.UniqueId, item.UniqueId);
            //Assert.AreEqual(result.Created, item.Created);

            //// However Updated and ETag have been updated.
            //Assert.AreNotEqual(result.Updated, item.Updated);
            //Assert.AreNotEqual(result.ETag, item.ETag);
        }

        public static async Task Test7Async()
        {
            // 初始化
            var client = new EveClient
            {
                BaseAddress = new Uri("http://127.0.0.1/vst/"),
                //Authenticator = new BasicAuthenticator("user", "pw")
            };

            // 为随后的请求设置目标资源
            client.ResourceName = "supplyitem";

            // DELETE Requests

            var items = await client.GetAsync<supplyitem>();
            if (client.HttpResponse.StatusCode != HttpStatusCode.OK)
                return;

            var item = items[0];

            // DELETE requests will silently perform a If-Match request so document
            // will only be deleted if its ETag matches the one on the server.
            // See http://python-eve.org/features#data-integrity-and-concurrency-control
            var message = await client.DeleteAsync(item);
            if (HttpStatusCode.OK != message.StatusCode)
                return;


        }

        //// Mapping JSON and Eve meta-fields to Classes

        //// You want to map Eve meta-fields to class properties by flagging them with
        //// the RemoteAttribute. Since these are usually consistent across API
        //// endpoints it is probably a good idea to provide a base class for your
        //// business objects to inherit from.
        public abstract class BaseClass
        {
            [JsonProperty("_id")]
            [Remote(Meta.DocumentId)]
            public string UniqueId { get; set; }

            [JsonProperty("_etag")]
            [Remote(Meta.ETag)]
            public string ETag { get; set; }

            [JsonProperty("_updated")]
            [Remote(Meta.LastUpdated)]
            public DateTime Updated { get; set; }

            [JsonProperty("_created")]
            [Remote(Meta.DateCreated)]
            public DateTime Created { get; set; }
        }

        public class EveLink
        {
            public string title { get; set; }
            public string href { get; set; }
        }

        public class EveLinks
        {
            public EveLink parent { get; set; }
            public EveLink self { get; set; }
        }

        public class EveMeta
        {
            public long page { get; set; }
            public long max_results { get; set; }
            public long total { get; set; }
        }

        public class EveGetResult<T>
        {
            [JsonProperty("_items")]
            public T[] Items { get; set; }

            [JsonProperty("_links")]
            public EveLinks Links { get; set; }

            [JsonProperty("_meta")]
            public EveMeta Meta { get; set; }
        }

        //// By default, snake_case conversion will be adopted when(de)serializing classes to json.
        ////For example, `MyClass.ThisIsAProperty` will be serialized to `this_is_a_property` in
        ////the json. If you want to change this behaviour, set the `ContractResolver` property
        ////accordingly.

        public static async Task Test8Async()
        {
            // 初始化
            var client = new EveClient
            {
                BaseAddress = new Uri("http://127.0.0.1/vst/"),
                //Authenticator = new BasicAuthenticator("user", "pw")
            };

            // 为随后的请求设置目标资源
            client.ResourceName = "supplyitem";

            // Raw GET Requests

            // You can use this method to perform parametrized queries.
            var query = @"supplyitem?where={""name"": ""stock_top_inst""}";

            // GetAsync will return a HttpResponseMessage which you can freely inspect.
            var response = await client.GetAsync(query);
            if (HttpStatusCode.OK != response.StatusCode)
                return;

            if ("application/json" != response.Content.Headers.ContentType.ToString())
                return;

            // Please note that you also get the HttpResponseMessage object with GetAsync<T> requests,exposed by the HttpResponse property.

            var jsonStr = await response.Content.ReadAsStringAsync();

            //var item = JsonConvert.DeserializeObject<supplyitem>(jsonStr);
            var res = JsonConvert.DeserializeObject<EveGetResult<supplyitem>>(jsonStr);

            foreach (var item in res.Items)
            {
                _logger.Info("{0} {1} {2}", item.name, item.time, item.tag);
            }
        }

        public static void GetCollectionNames()
        {
            var client = new EveClient
            {
                BaseAddress = new Uri("http://127.0.0.1/vst/"),
                //Authenticator = new BasicAuthenticator("user", "pw")
            };

            var res = client.GetAsync(string.Empty).Result;
            if (!res.IsSuccessStatusCode)
                return;

            var jsonStr = res.Content.ReadAsStringAsync().Result;
            var top = Newtonsoft.Json.JsonConvert.DeserializeObject<Invest.Data.EveGetTopResult>(jsonStr);
            if (top == null)
                return;

            foreach (var item in top.Links.child)
            {
                _logger.Info(item.href);
            }
        }

        public static void Filter()
        {
            var fd = Builders<supplyitem>.Filter.Eq(item => item.name, "test");

            _logger.Info(fd.ToString());
        }

        public static void RestApi()
        {
            var repo = new RestRepo("aa");
            if (!repo.Init("http://127.0.0.1/vst/"))
                return;

            var cols = repo.GetCollectionNames();
            foreach (var item in cols)
            {
                _logger.Info("集合：{0}", item);
            }

            var bbs = repo.FindAll<bond_basic>();
            foreach (var item in bbs)
            {
                _logger.Info("{0} {1}", item.name, item.ts_code);
            }

            var fbs = repo.FindAll<fund_basic>();
            foreach (var item in fbs)
            {
                _logger.Info("{0} {1}", item.name, item.ts_code);
            }

            var ftbs = repo.FindAll<future_basic>();
            foreach (var item in ftbs)
            {
                _logger.Info("{0} {1}", item.name, item.ts_code);
            }

            var obs = repo.FindAll<option_basic>();
            foreach (var item in obs)
            {
                _logger.Info("{0} {1}", item.name, item.ts_code);
            }

            var sbs = repo.FindAll<stock_basic>();
            foreach (var item in sbs)
            {
                _logger.Info("{0} {1}", item.name, item.ts_code);
            }

            var sibs = repo.FindAll<stock_index_basic>();
            foreach (var item in sibs)
            {
                _logger.Info("{0} {1}", item.name, item.ts_code);
            }
        }
    }
}
